# Copyright (C) 2010 Brett Hartshorn
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# 
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

from ogreEx.context import set__name__

set__name__(__name__)

import bpy
#from ogreEx.blender.props import IntProperty, StringProperty, EnumProperty, BoolProperty, FloatProperty
from ogreEx.blender.props import IntProperty, StringProperty, BoolProperty, FloatProperty, EnumProperty
from ogreEx.config import  getConfig
from ogreEx.ui.header.CINFO_HT_microheader import INFO_HT_microheader
from ogreEx.ui.header.CINFO_HT_myheader import INFO_HT_myheader
from ogreEx.ui.menu.CINFO_MT_groups import INFO_MT_groups
from ogreEx.ui.menu.CINFO_MT_instances import INFO_MT_instances
from ogreEx.ui.menu.CINFO_MT_ogre_shader_pass_attributes import INFO_MT_ogre_shader_pass_attributes
from ogreEx.ui.menu.CINFO_MT_ogre_shader_texture_attributes import INFO_MT_ogre_shader_texture_attributes
from ogreEx.ui.menu.CMENU_preview_material_text import MENU_preview_material_text
from ogreEx.ui.menu.CMiniReport import MiniReport
from ogreEx.ui.menu.doc.C_ogredoc_Animation_System import _ogredoc_Animation_System
from ogreEx.ui.menu.doc.C_ogredoc_Bugs import _ogredoc_Bugs
from ogreEx.ui.menu.doc.C_ogredoc_FAQ import _ogredoc_FAQ
from ogreEx.ui.menu.doc.C_ogredoc_Installing import _ogredoc_Installing
from ogreEx.ui.menu.doc.C_ogredoc_Physics import _ogredoc_Physics
from ogreEx.ui.menu.doc.CINFO_MT_ogre_docs import INFO_MT_ogre_docs
from ogreEx.ui.menu.doc.CINFO_MT_ogre_helper import INFO_MT_ogre_helper
from ogreEx.ui.operator.CBlender2Ogre_ConfigOp import Blender2Ogre_ConfigOp
from ogreEx.ui.operator.CINFO_MT_group import INFO_MT_group
from ogreEx.ui.operator.CINFO_MT_instance import INFO_MT_instance
from ogreEx.ui.operator.CINFO_OT_createOgreExport import INFO_OT_createOgreExport
from ogreEx.ui.operator.CINFO_OT_createRealxtendExport import INFO_OT_createRealxtendExport
from ogreEx.context import get_header_
from ogreEx.context import set_header_
from ogreEx.ogre.shader_program import  update_parent_material_path
from ogreEx.ui.operator.CJmonkeyPreviewOp import JmonkeyPreviewOp
from ogreEx.ui.operator.COgreCollisionOp import OgreCollisionOp
from ogreEx.ui.operator.COgreMeshyPreviewOp import OgreMeshyPreviewOp
from ogreEx.ui.operator.COgreToggleInterfaceOp import OgreToggleInterfaceOp
from ogreEx.ui.operator.CTundraPreviewOp import TundraPreviewOp
from ogreEx.ui.operator.CTundra_ExitOp import Tundra_ExitOp
from ogreEx.ui.operator.CTundra_PhysicsDebugOp import Tundra_PhysicsDebugOp
from ogreEx.ui.operator.CTundra_StartPhysicsOp import Tundra_StartPhysicsOp
from ogreEx.ui.operator.CTundra_StopPhysicsOp import Tundra_StopPhysicsOp
from ogreEx.ui.operator.C_create_new_material_layer_helper import _create_new_material_layer_helper
from ogreEx.ui.operator.CbpyShaders import bpyShaders
from ogreEx.ui.operator.PopUpDialogOperator import PopUpDialogOperator
from ogreEx.ui.panel.COgreSkyPanel      import OgreSkyPanel
from ogreEx.ui.panel.CPANEL_Collision   import PANEL_Collision
from ogreEx.ui.panel.CPANEL_Configure   import PANEL_Configure
from ogreEx.ui.panel.CPANEL_MultiResLOD import PANEL_MultiResLOD
from ogreEx.ui.panel.CPANEL_Object      import PANEL_Object
from ogreEx.ui.panel.CPANEL_Physics     import PANEL_Physics
from ogreEx.ui.panel.CPANEL_Speaker     import PANEL_Speaker
from ogreEx.ui.panel.CPANEL_Textures    import PANEL_Textures
from ogreEx.ui.panel.CPANEL_node_editor_ui import PANEL_node_editor_ui
from ogreEx.ui.panel.CPANEL_node_editor_ui_extra import PANEL_node_editor_ui_extra
from ogreEx.ui.panel.CPANEL_properties_window_ogre_material import PANEL_properties_window_ogre_material
from ogreEx.ui.panel.MatPass.all import MatPass1, MatPass2, MatPass3, MatPass4, MatPass5, MatPass6, MatPass7, MatPass8
from ogreEx.ui.restore_minimal_interface import restore_minimal_interface

VERSION = '0.6.0'

'''
CHANGELOG
    0.6.0
    * patched to work with 2.66.
    0.5.9
    * apply patch from Thomas for Blender 2.6x support
    0.5.8
    * Clean all names that will be used as filenames on disk. Adjust all places
      that use these names for refs instead of ob.name/ob.data.name. Replaced chars
      are \, /, :, *, ?, ", <, >, | and spaces. Tested on work with ogre 
      material, mesh and skeleton writing/refs inside the files and txml refs.
      Shows warning at final report if we had to resort to the renaming so user 
      can possibly rename the object.
    * Added silent auto update checks if blender2ogre was installed using
      the .exe installer. This will keep people up to date when new versions are out.
    * Fix tracker issue 48: Needs to check if outputting to /tmp or 
      ~/.wine/drive_c/tmp on Linux. Thanks to vax456 for providing the patch,
      added him to contributors. Preview mesh's are now placed under /tmp 
      on Linux systems if the OgreMeshy executable ends with .exe
    * Fix tracker issue 46: add operationtype to <submesh>
    * Implement a modal dialog that reports if material names have invalid
      characters and cant be saved on disk. This small popup will show until
      user presses left or right mouse (anywhere).
    * Fix tracker issue 44: XML Attributes not properly escaped in .scene file
    * Implemented reading OgreXmlConverter path from windows registry.
      The .exe installer will ship with certain tools so we can stop guessing
      and making the user install tools separately and setting up paths.
    * Fix bug that .mesh files were not generated while doing a .txml export.
      This was result of the late 2.63 mods that forgot to update object
      facecount before determining if mesh should be exported.
    * Fix bug that changed settings in the export dialog were forgotten when you
      re-exported without closing blender. Now settings should persist always
      from the last export. They are also stored to disk so the same settings
      are in use when if you restart Blender.
    * Fix bug that once you did a export, the next time the export location was
      forgotten. Now on sequential exports, the last export path is remembered in
      the export dialog.
    * Remove all local:// from asset refs and make them relative in .txml export.
      Having relative refs is the best for local preview and importing the txml
      to existing scenes.
    * Make .material generate what version of this plugins was used to generate
      the material file. Will be helpful in production to catch things.
      Added pretty printing line endings so the raw .material data is easier to read.
    * Improve console logging for the export stages. Run Blender from
      cmd prompt to see this information.
    * Clean/fix documentation in code for future development
    * Add todo to code for future development
    * Restructure/move code for easier readability
    * Remove extra white spaces and convert tabs to space
    0.5.7
    * Update to Blender 2.6.3.
    * Fixed xz-y Skeleton rotation (again)
    * Added additional Keyframe at the end of each animation to prevent 
      ogre from interpolating back to the start
    * Added option to ignore non-deformable bones
    * Added option to export nla-strips independently from each other

TODO
    * Remove this section and integrate below with code :)
    * Fix terrain collision offset bug
    * Add realtime transform (rotation is missing)
    * Fix camera rotated -90 ogre-dot-scene
    * Set description field for all pyRNA
'''

bl_info = {
    "name": "OGRE Exporter Ex (.scene, .mesh, .skeleton) and RealXtend (.txml)",
    "author": "Brett, S.Rombauts, F00bar, Waruck, Mind Calamity, Mr.Magne, Jonne Nauha, vax456",
    "version": (0, 6, 0),
    "blender": (2, 6, 6),
    "location": "File > Export...",
    "description": "Export to Ogre xml and binary formats",
    "wiki_url": "http://code.google.com/p/blender2ogre/w/list",
    "tracker_url": "http://code.google.com/p/blender2ogre/issues/list",
    "category": "Import-Export"}

###### imports #####
import os
import sys

#from bpy.props import *


## Make sure we can import from same directory
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
if SCRIPT_DIR not in sys.path: sys.path.append( SCRIPT_DIR )

## Avatar
bpy.types.Object.use_avatar         = BoolProperty   (name='enable avatar'        ,default=False                       ,description='enables EC_Avatar'                                   )
bpy.types.Object.avatar_reference   = StringProperty (name='avatar reference'     ,default= ''   ,maxlen=128           ,description='sets avatar reference URL'                           )
# Tundra IDs
bpy.types.Object.uid                = IntProperty    (name="unique ID"            ,default=  0   ,min=0   ,max=2**14   ,description="unique ID for Tundra"                                )
# Rendering
bpy.types.Object.use_draw_distance  = BoolProperty   (name='enable draw distance' ,default=False                       ,description='use LOD draw distance'                               )
bpy.types.Object.draw_distance      = FloatProperty  (name='draw distance'        ,default=  0.0 ,min=0.0 ,max=10000.0 ,description='distance at which to begin drawing object'           )
bpy.types.Object.cast_shadows       = BoolProperty   (name='cast shadows'         ,default=False                       ,description='cast shadows'                                        )
bpy.types.Object.use_multires_lod   = BoolProperty   (name='Enable Multires LOD'  ,default=False                       ,description='enables multires LOD'                                )
bpy.types.Object.multires_lod_range = FloatProperty  (name='multires LOD range'   ,default= 30.0 ,min=0.0 ,max=10000.0 ,description='far distance at which multires is set to base level' )

## Physics
_physics_modes =  [
    ('NONE'       ,'NONE'       ,'no physics' ),
    ('RIGID_BODY' ,'RIGID_BODY' ,'rigid body' ),
    ('SOFT_BODY'  ,'SOFT_BODY'  ,'soft body'  ),
]

_collision_modes =  [
    ('NONE'         ,'NONE'      ,'no collision'                                ),
    ('PRIMITIVE'    ,'PRIMITIVE' ,'primitive collision type'                    ),
    ('MESH'         , 'MESH'     ,'triangle-mesh or convex-hull collision type' ),
    ('DECIMATED'    ,'DECIMATED' ,'auto-decimated collision type'               ),
    ('COMPOUND'     ,'COMPOUND'  ,'children primitive compound collision type'  ),
    ('TERRAIN'      ,'TERRAIN'   ,'terrain (height map) collision type'         ),
]

bpy.types.Object.physics_mode = EnumProperty(
    items = _physics_modes, 
    name = 'physics mode', 
    description='physics mode', 
    default='NONE'
)
bpy.types.Object.physics_friction          = FloatProperty (name='Simple Friction'         ,description='physics friction'              ,default=  0.1  ,min= 0.0 ,max=1.0  )
bpy.types.Object.physics_bounce            = FloatProperty (name='Simple Bounce'           ,description='physics bounce'                ,default=  0.01 ,min= 0.0 ,max=1.0  )
bpy.types.Object.collision_terrain_x_steps = IntProperty   (name="Ogre Terrain: x samples" ,description="resolution in X of height map" ,default= 64    ,min= 4   ,max=8192 )
bpy.types.Object.collision_terrain_y_steps = IntProperty   (name="Ogre Terrain: y samples" ,description="resolution in Y of height map" ,default= 64    ,min= 4   ,max=8192 )

bpy.types.Object.collision_mode = EnumProperty(
    items = _collision_modes, 
    name = 'primary collision mode', 
    description='collision mode', 
    default='NONE'
)

bpy.types.Object.subcollision = BoolProperty(
    name="collision compound", description="member of a collision compound", default=False)

## Sound
bpy.types.Speaker.play_on_load = BoolProperty(name='play on load'     ,default=False )
bpy.types.Speaker.loop         = BoolProperty(name='loop sound'       ,default=False )
bpy.types.Speaker.use_spatial  = BoolProperty(name='3D spatial sound' ,default=True  )

from ogreEx.constants import _IMAGE_FORMATS

bpy.types.Image.use_convert_format = BoolProperty( name='use convert format', default=False )
bpy.types.Image.convert_format = EnumProperty( items=_IMAGE_FORMATS, name='convert to format',  description='converts to image format using imagemagick', default='NONE' )
bpy.types.Image.jpeg_quality = IntProperty(
    name="jpeg quality", description="quality of jpeg", 
    default=80, min=0, max=100)

bpy.types.Image.use_color_quantize        = BoolProperty (name='use color quantize'        ,default=False )
bpy.types.Image.use_color_quantize_dither = BoolProperty (name='use color quantize dither' ,default=True  )
bpy.types.Image.color_quantize            = IntProperty  (name="color quantize"            ,default=32, min=2, max=256, description="reduce to N colors (requires ImageMagick)")
bpy.types.Image.use_resize_half           = BoolProperty (name='resize by 1/2'             ,default=False )
bpy.types.Image.use_resize_absolute       = BoolProperty (name='force image resize'        ,default=False )
bpy.types.Image.resize_x                  = IntProperty  (name="resize X"                  ,default=256, min=2, max=4096, description="only if image is larger than defined, use ImageMagick to resize it down")
bpy.types.Image.resize_y                  = IntProperty  (name="resize Y"                  ,default=256, min=2, max=4096, description="only if image is larger than defined, use ImageMagick to resize it down")

# Materials

# ..Material.ogre_depth_write = AUTO|ON|OFF
bpy.types.Material.ogre_depth_write = BoolProperty( name='depth write', default=True )

# If depth-buffer checking is on, whenever a pixel is about to be written to
# the frame buffer the depth buffer is checked to see if the pixel is in front
# of all other pixels written at that point. If not, the pixel is not written.
# If depth checking is off, pixels are written no matter what has been rendered before.
bpy.types.Material.ogre_depth_check = BoolProperty( name='depth check', default=True )

# Sets whether this pass will use 'alpha to coverage', a way to multisample alpha
# texture edges so they blend more seamlessly with the background. This facility
# is typically only available on cards from around 2006 onwards, but it is safe to
# enable it anyway - Ogre will just ignore it if the hardware does not support it.
# The common use for alpha to coverage is foliage rendering and chain-link fence style textures.
bpy.types.Material.ogre_alpha_to_coverage = BoolProperty( name='multisample alpha edges', default=False )

# This option is usually only useful if this pass is an additive lighting pass, and is
# at least the second one in the technique. Ie areas which are not affected by the current
# light(s) will never need to be rendered. If there is more than one light being passed to
# the pass, then the scissor is defined to be the rectangle which covers all lights in screen-space.
# Directional lights are ignored since they are infinite. This option does not need to be specified
# if you are using a standard additive shadow mode, i.e. SHADOWTYPE_STENCIL_ADDITIVE or
# SHADOWTYPE_TEXTURE_ADDITIVE, since it is the default behaviour to use a scissor for each additive
# shadow pass. However, if you're not using shadows, or you're using Integrated Texture Shadows
# where passes are specified in a custom manner, then this could be of use to you.
bpy.types.Material.ogre_light_scissor     = BoolProperty(name='light scissor'     ,default=False)
bpy.types.Material.ogre_light_clip_planes = BoolProperty(name='light clip planes' ,default=False)

# TODO set description for all pyRNA
bpy.types.Material.ogre_normalise_normals = BoolProperty( name='normalise normals', default=False,
    description='''
Scaling objects causes normals to also change magnitude, which can throw off your lighting calculations. By default, the SceneManager detects this and will automatically re-normalise normals for any scaled object, but this has a cost. If you'd prefer to control this manually, call SceneManager::setNormaliseNormalsOnScale(false) and then use this option on materials which are sensitive to normals being resized.
''')

# Sets whether or not dynamic lighting is turned on for this pass or not. If lighting is turned off,
# all objects rendered using the pass will be fully lit. This attribute has no effect if a vertex program is used.
bpy.types.Material.ogre_lighting = BoolProperty( name='dynamic lighting', default=True )

# If colour writing is off no visible pixels are written to the screen during this pass. You might think
# this is useless, but if you render with colour writing off, and with very minimal other settings,
# you can use this pass to initialise the depth buffer before subsequently rendering other passes which
# fill in the colour data. This can give you significant performance boosts on some newer cards, especially
# when using complex fragment programs, because if the depth check fails then the fragment program is never run.
bpy.types.Material.ogre_colour_write = BoolProperty( name='color-write', default=True )

# Fixed pipeline is oldschool
# todo: whats the meaning of this?
bpy.types.Material.use_fixed_pipeline = BoolProperty( name='fixed pipeline', default=True )

# hidden option - gets turned on by operator
# todo: What is a hidden option, is this needed?
bpy.types.Material.use_material_passes       = BoolProperty(name='use ogre extra material passes (layers)' ,default=False )
bpy.types.Material.use_in_ogre_material_pass = BoolProperty(name='Layer Toggle'                            ,default=True  )
bpy.types.Material.use_ogre_advanced_options = BoolProperty(name='Show Advanced Options'                   ,default=False )
bpy.types.Material.use_ogre_parent_material  = BoolProperty(name='Use Script Inheritance'                  ,default=False )
bpy.types.Material.ogre_parent_material      = EnumProperty(name="Script Inheritence", items=[], description='ogre parent material class',)#default='NONE',

bpy.types.Material.ogre_polygon_mode = EnumProperty(
    items=[
        ('solid'     ,'solid'     ,'SOLID'     ),
        ('wireframe' ,'wireframe' ,'WIREFRAME' ),
        ('points'    ,'points'    ,'POINTS'    ),
    ],
    name='faces draw type', 
    description="ogre face draw mode", 
    default='solid'
)

bpy.types.Material.ogre_shading = EnumProperty(
    items=[
        ('flat'    ,'flat'    ,'FLAT'    ),
        ('gouraud' ,'gouraud' ,'GOURAUD' ),
        ('phong'   ,'phong'   ,'PHONG'   ),
    ],
    name='hardware shading', 
    description="Sets the kind of shading which should be used for representing dynamic lighting for this pass.", 
    default='gouraud'
)

bpy.types.Material.ogre_cull_hardware = EnumProperty(
    items=[
        ('clockwise'     ,'clockwise'     ,'CLOCKWISE'         ),
        ('anticlockwise' ,'anticlockwise' ,'COUNTER CLOCKWISE' ),
        ('none'          ,'none'          ,'NONE'              ),
    ],
    name='hardware culling', 
    description="If the option 'cull_hardware clockwise' is set, all triangles whose vertices are viewed in clockwise order from the camera will be culled by the hardware.", 
    default='clockwise'
)

bpy.types.Material.ogre_transparent_sorting = EnumProperty(
    items=[
        ('on'    ,'on'    ,'ON'       ),
        ('off'   ,'off'   ,'OFF'      ),
        ('force' ,'force' ,'FORCE ON' ),
    ],
    name='transparent sorting', 
    description="By default all transparent materials are sorted such that renderables furthest away from the camera are rendered first. This is usually the desired behaviour but in certain cases this depth sorting may be unnecessary and undesirable. If for example it is necessary to ensure the rendering order does not change from one frame to the next. In this case you could set the value to 'off' to prevent sorting.", 
    default='on'
)

bpy.types.Material.ogre_illumination_stage = EnumProperty(
    items=[
        (''          ,''          ,'autodetect' ),
        ('ambient'   ,'ambient'   ,'ambient'    ),
        ('per_light' ,'per_light' ,'lights'     ),
        ('decal'     ,'decal'     ,'decal'      )
    ],
    name='illumination stage', 
    description='When using an additive lighting mode (SHADOWTYPE_STENCIL_ADDITIVE or SHADOWTYPE_TEXTURE_ADDITIVE), the scene is rendered in 3 discrete stages, ambient (or pre-lighting), per-light (once per light, with shadowing) and decal (or post-lighting). Usually OGRE figures out how to categorise your passes automatically, but there are some effects you cannot achieve without manually controlling the illumination.', 
    default=''
)

_ogre_depth_func =  [
    ('less_equal'    ,'less_equal'    , '<='    ),
    ('less'          ,'less'          , '<'     ),
    ('equal'         ,'equal'         , '=='    ),
    ('not_equal'     ,'not_equal'     , '!='    ),
    ('greater_equal' ,'greater_equal' , '>='    ),
    ('greater'       ,'greater'       , '>'     ),
    ('always_fail'   ,'always_fail'   , 'false' ),
    ('always_pass'   ,'always_pass'   , 'true'  ),
]
bpy.types.Material.ogre_depth_func = EnumProperty(
    items=_ogre_depth_func, 
    name='depth buffer function', 
    description='If depth checking is enabled (see depth_check) a comparison occurs between the depth value of the pixel to be written and the current contents of the buffer. This comparison is normally less_equal, i.e. the pixel is written if it is closer (or at the same distance) than the current contents', 
    default='less_equal'
)



_ogre_scene_blend_ops =  [
    ('add'              ,'add'              ,'DEFAULT'          ),
    ('subtract'         ,'subtract'         ,'SUBTRACT'         ),
    ('reverse_subtract' ,'reverse_subtract' ,'REVERSE SUBTRACT' ),
    ('min'              ,'min'              ,'MIN'              ),
    ('max'              ,'max'              ,'MAX'              ),

]
bpy.types.Material.ogre_scene_blend_op = EnumProperty(
    items=_ogre_scene_blend_ops, 
    name='scene blending operation', 
    description='This directive changes the operation which is applied between the two components of the scene blending equation', 
    default='add'
)

_ogre_scene_blend_types =  [
    ('one zero'     ,'one zero'     ,'DEFAULT'),
    ('alpha_blend'  ,'alpha_blend'  ,"The alpha value of the rendering output is used as a mask. Equivalent to 'scene_blend src_alpha one_minus_src_alpha'"),
    ('add'          ,'add'          ,"The colour of the rendering output is added to the scene. Good for explosions, flares, lights, ghosts etc. Equivalent to 'scene_blend one one'."),
    ('modulate'     ,'modulate'     ,"The colour of the rendering output is multiplied with the scene contents. Generally colours and darkens the scene, good for smoked glass, semi-transparent objects etc. Equivalent to 'scene_blend dest_colour zero'"),
    ('colour_blend' ,'colour_blend' ,'Colour the scene based on the brightness of the input colours, but dont darken. Equivalent to "scene_blend src_colour one_minus_src_colour"'),
]
for mode in 'dest_colour src_colour one_minus_dest_colour dest_alpha src_alpha one_minus_dest_alpha one_minus_src_alpha'.split():
    _ogre_scene_blend_types.append( ('one %s'%mode, 'one %s'%mode, '') )
del mode

bpy.types.Material.ogre_scene_blend = EnumProperty(
    items=_ogre_scene_blend_types, 
    name='scene blend', 
    description='blending operation of material to scene', 
    default='one zero'
)

#####################################################
## Game Logic Documentation

_game_logic_intro_doc_ = '''
Hijacking the BGE

Blender contains a fully functional game engine (BGE) that is highly useful for learning the concepts of game programming by breaking it down into three simple parts: Sensor, Controller, and Actuator.  An Ogre based game engine will likely have similar concepts in its internal API and game logic scripting.  Without a custom interface to define game logic, very often game designers may have to resort to having programmers implement their ideas in purely handwritten script.  This is prone to breakage because object names then end up being hard-coded.  Not only does this lead to non-reusable code, its also a slow process.  Why should we have to resort to this when Blender already contains a very rich interface for game logic?  By hijacking a subset of the BGE interface we can make this workflow between game designer and game programmer much better.

The OgreDocScene format can easily be extened to include extra game logic data.  While the BGE contains some features that can not be easily mapped to other game engines, there are many are highly useful generic features we can exploit, including many of the Sensors and Actuators.  Blender uses the paradigm of: 1. Sensor -> 2. Controller -> 3. Actuator.  In pseudo-code, this can be thought of as: 1. on-event -> 2. conditional logic -> 3. do-action.  The designer is most often concerned with the on-events (the Sensors), and the do-actions (the Actuators); and the BGE interface provides a clear way for defining and editing those.  Its a harder task to provide a good interface for the conditional logic (Controller), that is flexible enough to fit everyones different Ogre engine and requirements, so that is outside the scope of this exporter at this time.  A programmer will still be required to fill the gap between Sensor and Actuator, but hopefully his work is greatly reduced and can write more generic/reuseable code.

The rules for which Sensors trigger which Actuators is left undefined, as explained above we are hijacking the BGE interface not trying to export and reimplement everything.  BGE Controllers and all links are ignored by the exporter, so whats the best way to define Sensor/Actuator relationships?  One convention that seems logical is to group Sensors and Actuators by name.  More complex syntax could be used in Sensor/Actuators names, or they could be completely ignored and instead all the mapping is done by the game programmer using other rules.  This issue is not easily solved so designers and the engine programmers will have to decide upon their own conventions, there is no one size fits all solution.
'''


_ogre_logic_types_doc_ = '''
Supported Sensors:
    . Collision
    . Near
    . Radar
    . Touching
    . Raycast
    . Message

Supported Actuators:
    . Shape Action*
    . Edit Object
    . Camera
    . Constraint
    . Message
    . Motion
    . Sound
    . Visibility

*note: Shape Action
The most common thing a designer will want to do is have an event trigger an animation.  The BGE contains an Actuator called "Shape Action", with useful properties like: start/end frame, and blending.  It also contains a property called "Action" but this is hidden because the exporter ignores action names and instead uses the names of NLA strips when exporting Ogre animation tracks.  The current workaround is to hijack the "Frame Property" attribute and change its name to "animation".  The designer can then simply type the name of the animation track (NLA strip).  Any custom syntax could actually be implemented here for calling animations, its up to the engine programmer to define how this field will be used.  For example: "*.explode" could be implemented to mean "on all objects" play the "explode" animation.

'''

#class _type(bpy.types.IDPropertyGroup):
#    name = StringProperty(name="jpeg format", description="", maxlen=64, default="")

#######################


def export_menu_func_ogre(self, context):
    op = self.layout.operator(INFO_OT_createOgreExport.bl_idname, text="Ogre3D (.scene and .mesh)")

def export_menu_func_realxtend(self, context):
    op = self.layout.operator(INFO_OT_createRealxtendExport.bl_idname, text="realXtend Tundra (.txml and .mesh)")

try: set_header_(bpy.types.INFO_HT_header)
except:
    print('---blender2ogre addon enable---')

from ogreEx.context import setUseTundra

def register():
    print('Starting blender2ogre', VERSION)
    #bpy.utils.register_module(__name__)    ## do not load all the ogre panels by default
    #set_header_(bpy.types.INFO_HT_header)
    #bpy.utils.unregister_class(get_header_())
    restore_minimal_interface()

    # only test for Tundra2 once - do not do this every panel redraw ##
    if os.path.isdir( getConfig()['TUNDRA_ROOT'] ): setUseTundra(True)
    else: setUseTundra(False)
    #if os.path.isdir( getConfig()['JMONKEY_ROOT'] ): setUseJmonkey(True)
    #else: setUseJmonkey(False)

    bpy.types.INFO_MT_file_export.append(export_menu_func_ogre      )
    bpy.types.INFO_MT_file_export.append(export_menu_func_realxtend )

    #bpy.utils.register_class(PopUpDialogOperator)    
    
    if os.path.isdir( getConfig()['USER_MATERIALS'] ):
        scripts,progs = update_parent_material_path( getConfig()['USER_MATERIALS'] )
        for prog in progs:
            print('Ogre shader program', prog.name)
    else:
        print('[WARNING]: Invalid my-shaders path' )

def unregister():
    print('Unloading blender2ogre', VERSION)
    header = get_header_()

    bpy.utils.unregister_module(__name__)
    if header: 
        bpy.utils.register_class(header)    
    bpy.types.INFO_MT_file_export.remove(export_menu_func_ogre      )
    bpy.types.INFO_MT_file_export.remove(export_menu_func_realxtend )
    #bpy.utils.unregister_class(PopUpDialogOperator)

## Blender world panel options for EC_SkyX creation
## todo: EC_SkyX has changes a bit lately, see that
## all these options are still correct and valid
## old todo (?): Move to tundra.py
bpy.types.World.ogre_skyX                   = BoolProperty  (name="enable sky"        ,default= False                      ,description="ogre sky"                                 )
bpy.types.World.ogre_skyX_time              = FloatProperty (name="Time Multiplier"   ,default=   0.3 ,min=0.0 ,max=   5.0 ,description="change speed of day/night cycle"          )
bpy.types.World.ogre_skyX_wind              = FloatProperty (name="Wind Direction"    ,default=  33.0 ,min=0.0 ,max= 360.0 ,description="change direction of wind"                 )
bpy.types.World.ogre_skyX_volumetric_clouds = BoolProperty  (name="volumetric clouds" ,default= True                       ,description="toggle ogre volumetric clouds"            )
bpy.types.World.ogre_skyX_cloud_density_x   = FloatProperty (name="Cloud Density X"   ,default=   0.1 ,min=0.0 ,max=   5.0 ,description="change density of volumetric clouds on X" )
bpy.types.World.ogre_skyX_cloud_density_y   = FloatProperty (name="Cloud Density Y"   ,default=   1.0 ,min=0.0 ,max=   5.0 ,description="change density of volumetric clouds on Y" )

###########################################################################

_check_all_=[
    Blender2Ogre_ConfigOp                  , # Operator -> @OPERATOR
    MiniReport                             , # Menu     -> @MINI             # Minimal Interface
    OgreCollisionOp                        , # Operator -> @OPERATOR
    PANEL_Physics                          , # Panel    -> @UI
    PANEL_Collision                        , # Panel    -> @UI
    PANEL_Configure                        , # Panel    -> @UI
    _create_new_material_layer_helper      , # Operator -> @OPERATOR
    PANEL_properties_window_ogre_material  , # Panel    -> @UI
    MatPass1                               , # Panel    -> @UI -> _OgreMatPass
    MatPass2                               , # Panel    -> @UI -> _OgreMatPass
    MatPass3                               , # Panel    -> @UI -> _OgreMatPass
    MatPass4                               , # Panel    -> @UI -> _OgreMatPass
    MatPass5                               , # Panel    -> @UI -> _OgreMatPass
    MatPass6                               , # Panel    -> @UI -> _OgreMatPass
    MatPass7                               , # Panel    -> @UI -> _OgreMatPass
    MatPass8                               , # Panel    -> @UI -> _OgreMatPass
    PANEL_Textures                         , # Panel    -> @UI
    OgreMeshyPreviewOp                     , # Operator -> @OPERATOR
    INFO_MT_ogre_helper                    , # Menu     <- _ogredoc_*, abstract
    INFO_MT_ogre_docs                      , # Menu     -> @OTHER
    INFO_MT_ogre_shader_pass_attributes    , # Menu     -> @OTHER
    INFO_MT_ogre_shader_texture_attributes , # Menu     -> @OTHER
    _ogredoc_Installing                    , # Menu     -> @ogredoc, INFO_MT_ogre_helper
    _ogredoc_FAQ                           , # Menu     -> @ogredoc, INFO_MT_ogre_helper
    _ogredoc_Animation_System              , # Menu     -> @ogredoc, INFO_MT_ogre_helper
    _ogredoc_Physics                       , # Menu     -> @ogredoc, INFO_MT_ogre_helper
    _ogredoc_Bugs                          , # Menu     -> @ogredoc, INFO_MT_ogre_helper
    INFO_OT_createOgreExport               , # Operator -> @MINI -> _OgreCommonExport_ # Minimal Interface
    INFO_OT_createRealxtendExport          , # Operator -> @MINI -> _OgreCommonExport_ # Minimal Interface
    INFO_MT_instances                      , # Menu     -> @OTHER
    INFO_MT_instance                       , # Operator -> @OPERATOR
    INFO_MT_groups                         , # Menu     -> @OTHER
    INFO_MT_group                          , # Operator -> @OPERATOR
    JmonkeyPreviewOp                       , # Operator -> @OPERATOR -> _OgreCommonExport_
    TundraPreviewOp                        , # Operator -> @OPERATOR -> _OgreCommonExport_
    Tundra_StartPhysicsOp                  , # Operator -> @OPERATOR
    Tundra_StopPhysicsOp                   , # Operator -> @OPERATOR
    Tundra_PhysicsDebugOp                  , # Operator -> @OPERATOR
    Tundra_ExitOp                          , # Operator -> @OPERATOR
    MENU_preview_material_text             , # Menu     -> @OTHER
    INFO_HT_myheader                       , # Header   -> @UI
    OgreToggleInterfaceOp                  , # Operator -> @OPERATOR         # Minimal Interface
    INFO_HT_microheader                    , # Header   -> @MINI             # Minimal Interface
    OgreSkyPanel                           , # Panel    -> @UI
    PANEL_Object                           , # Panel    -> @UI
    PANEL_Speaker                          , # Panel    -> @UI
    PANEL_MultiResLOD                      , # Panel    -> @UI
    bpyShaders                             , # Operator -> @OPERATOR
    PANEL_node_editor_ui                   , # Panel    -> @UI
    PANEL_node_editor_ui_extra             , # Panel    -> @UI
]

## Blender addon main entry point.
## Allows directly running by "blender --python blender2ogre.py"

if __name__ == "__main__":
    register()
